APIキーが必要なAPI Gatewayで、APIキーが無い場合に401を返す (AWS SAM with OpenAPI)
APIキーが無い場合に401を返すAPI Gatewayを作成してみました。
2024.02.09
APIキーが必要なAPI Gatewayでは、APIキーが無い場合に403が返ります。
- APIキーが無い: 403
- APIキーはあるけど、違う:403
これらについて、403ではなく、401を返すようにしてみました。
おすすめの方
- AWS SAMでAPI GatewayとLambdaを作成したい方
- AWS SAMでOpenAPIでAPI Gatewayを作成したい方
- AWS SAMでAPIキーが必要なAPI Gatewayを作成したい方
- OpenAPIで作るAPI GatewayでAPIキーが無い場合に401を返したい方
APIを作成する
sam init
sam init \ --runtime python3.11 \ --name api-gateway-need-api-key-sample \ --app-template hello-world \ --no-tracing \ --no-application-insights \ --structured-logging \ --package-type Zip
AWS SAMテンプレート
AWSTemplateFormatVersion: '2010-09-09' Transform: AWS::Serverless-2016-10-31 Description: ApiGateway-Need-API-Key-Sample Resources: MyApi: Type: AWS::Serverless::Api Properties: StageName: dev OpenApiVersion: 3.0.1 ApiKeySourceType: HEADER Auth: ApiKeyRequired: true UsagePlan: CreateUsagePlan: PER_API UsagePlanName: Basic-usage-plan-of-AWS-SAM-api-gateway-plan Quota: Limit: 500 Period: MONTH Throttle: BurstLimit: 100 RateLimit: 50 DefinitionBody: Fn::Transform: Name: AWS::Include Parameters: Location: s3://cm-fujii.genki-deploy/ApiGateway-Need-API-Key-Sample/api.yaml HelloWorldFunction: Type: AWS::Serverless::Function Properties: CodeUri: hello_world/ Handler: app.lambda_handler Runtime: python3.9 Timeout: 5 Events: HelloWorld: Type: Api Properties: Path: /hello Method: get RestApiId: !Ref MyApi HelloWorldFunctionLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub /aws/lambda/${HelloWorldFunction}
OpenAPI
「x-amazon-apigateway-gateway-responses」を利用して、401を返します。
openapi: 3.0.1 info: title: ApiGateway-Need-API-Key-Sample version: 1.0.0 # https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/supported-gateway-response-types.html x-amazon-apigateway-gateway-responses: INVALID_API_KEY: statusCode: 401 paths: /hello: get: tags: - hello responses: 200: $ref: "#/components/responses/200" 401: $ref: "#/components/responses/401" 403: $ref: "#/components/responses/403" 500: $ref: "#/components/responses/500" security: - apiKey: [] x-amazon-apigateway-integration: type: aws_proxy uri: 'Fn::Sub': >- arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloWorldFunction.Arn}/invocations httpMethod: POST responses: default: statusCode: 200 passthroughBehavior: when_no_templates contentHandling: CONVERT_TO_TEXT components: securitySchemes: apiKey: type: apiKey name: x-api-key in: header responses: 200: description: Success 401: description: Unauthorized 403: description: User or client is not authorized. 500: description: Internal Server Error
Lambdaコード
import json def lambda_handler(event, context): return { "statusCode": 200, "body": json.dumps( { "message": "hello world", } ), }
デプロイ
aws s3 cp \ api.yaml \ s3://cm-fujii.genki-deploy/ApiGateway-Need-API-Key-Sample/api.yaml sam package \ --output-template-file packaged.yaml \ --s3-bucket cm-fujii.genki-deploy sam deploy \ --template-file packaged.yaml \ --stack-name ApiGateway-Need-API-Key-Sample-Stack \ --s3-bucket cm-fujii.genki-deploy \ --capabilities CAPABILITY_NAMED_IAM \ --no-fail-on-empty-changeset
APIの動作を確認する
「HEADER」を設定しているため、ヘッダーの「x-api-key」にAPIキーを設定します。
APIキーが無い場合は、401が返ってくる
$ curl -X GET -I https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello HTTP/2 401
APIキーがある場合(違う)は、401が返ってくる
$ curl -X GET -I https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello \ -H "x-api-key: invalid-api-key" HTTP/2 401
APIキーがある場合(合っている)は、200が返ってくる
$ curl -X GET -I https://xxx.execute-api.ap-northeast-1.amazonaws.com/dev/hello \ -H "x-api-key: valid-api-key" HTTP/2 200